Monte Carlo Scheme for Asian and Lookback Option Pricing

ZiJian Feng
690127127@qq.com
September, 2021

1. Introduction

This is a mini project to price exotic options for the appropriate form of payoff, to consider Asian and lookback options, which are path-dependent options. Firstly, we define state variables as:

Mean: A=mean(Si;iI)

Max: M=max(Si;iI)

Min: m=min(Si;iI)

Where, I is a set of sampling index from asset path by a certain period which can be chosen as 1 day,1 week,1 month, 1 quarter,semi-year,1 year and so on. Mean is a function of set to return the mean of its elements Max is a function of set to return the maximum of its elements. Min is a function of set to return the minimum of its elements.

Then, We set E is delivery price, the payoff functions of different exotic options we considered are listed as follow:

option payoff function
Asian call option with fixed delivery price: max(AE,0)
Asian put option with fixed delivery price: max(EA,0)
Asian call option with floating delivery price: max(AST,0)
Asian put option with floating delivery price: max(STA,0)
Lookback call option with fixed delivery price: max(ME,0)
Lookback put option with fixed delivery price: max(Em,0)
Lookback call option with floating delivery price: max(MST,0)
Lookback put option with floating delivery price: max(STm,0)

It is hard to find closed-form solutions for prices. More often than not we must solve option-pricing problems by numerical means. The most useful numerical techniques are Monte Carlo simulations and finite-difference methods.

However, path-dependent options are added demension as a state variable so it is difficult to deduce PDE and implement finite-difference methods. Thus, this project mainly consider Monte Carlo scheme.

Monte Carlo methods are any process that consumes random numbers. These are part of computational algorithms which are based on random sampling to obtain numerical results. Monte Carlo methods are proved to be a very valuable and flexible computational tool in finance and is one of the most widely used methods for optimization and numerical integration problems.

These methods are widely used in high dimensional problems. pricing exotics and complex derivatives where closed form solutions are not directly available. Monte Carlo methods are not just adapted in pricing complex derivatives, It is also extensively used in estimating the portfolio risk such as Value-at-Risk and Expected Shortfall and used in the calculation of worst-case scenarios in stress testing. The downside to that is, it is very computational intensive and demanding.

The mathematics that we need to perform a Monte Carlo simulation can be very basic. Use the expected value of the discounted payoff under the risk-neutral density Q

V(S,t)=er(Tt)EQ[Payoff(ST)]

Martingale theory can deduce arbitrage-free principle.It is also seen that Martingale theory is consistent with Black-scholes PDE by using Feynman-Kac formula.Thus,justification for the Martingale theory to price is obvious.

The reasons we choose the Monte Carlo scheme are still including:

  • Complex path dependency can often be easily incorporated: We do not have to deduce PDEs which can not be understood easily;
  • Many contracts can be priced at the same time: We can use a collect of simulated paths to price Asian and lookback options;
  • It is computationally quite efficient in high dimensions: We just need to caculate a added state variable which do not cost many time.

2. Numerical Procedure

The numerical procedure of Monte Carlo algorithm for option pricing is generally summarized as follow:

  • Step1 : Simulate the risk-neutral Brownian motion starting at today’s value of the asset S0 over the required time horizon. This gives one realization of the underlying price path.

  • Step2 : For this realization calculate the option payoff. Note that we have to caculate state variables based on simulated price path which are putted into payoff function

  • Step3 : Perform many more such realizations over the time horizon.

  • Step4 : Calculate the average payoff over all realizations.
  • Step5 : Take the present value of this average, this is the option value.

The key procedure is how to simulate the underlying price path. Price process follows the risk-neutral stochastic differential equation which may not have closed-form solutions. A general method that always works is to use a discrete version of the stochastic differential equation for price of which a typical representative is Euler-Maruyama scheme

δS=rSδt+σSδtϕ,

where ϕ is from a standardized Normal distribution, r is risk-free interest rate

This method has an error of O(δt). Because we are only simulating a finite number of an infinite number of possible paths, the error due to using N realizations of the asset price paths is O(1N).

We set an initial example using the following set of sample data:

  • Today's stock price S0 = 100
  • Strike E = 100
  • Time to expiry (T-t)= 1 year
  • volatility = 20%
  • constant risk-free interest rate r = 5%

It is necessary to set some numerical parameters:

  • δt=1252, meaning every day
  • N=100000, we have balanced between precision and efficiency
  • sampling period usually equals 21 if there is no specification

This project is aimed to solve initial example by choose different sampling periods, such as 1 day,1 week,1 month,1 quarter,semi-year,1 year. Then we set sampling period to be 1 month, vary the data to see the affect on the option prices. In the appendix we also make a detailed exploration to analyse error.

3. Coding Preparation

It is necessary to set basic configuration before explorate. Some required libraries will be imported.Some functions will be also defined, though may be redefined below by different problem.

Import Required Libraries

In [72]:
# Importing libraries
import pandas as pd
from numpy import *

# Libraries for plotting
import matplotlib.pyplot as plt
import cufflinks as cf
cf.set_config_file(offline=True)

# Set max row to 300
pd.set_option('display.max_rows', 300)

# Ignore warnings
import warnings
warnings.filterwarnings('ignore')

User Defined Function

The function simulate_path is used to simulate the underlying asset price paths. it has 6 aguments:

  • s0: initial spot level [float]
  • mu: mu = rf in risk neutral framework / year [float]
  • sigma: volatility / year [float]
  • horizon: time horizion / year [float]
  • timesteps: number of time steps [int]
  • n_sims: number of simulation [int]

The return is a array shape of which is (timesteps+1)×n_sims.Its rows represent time, columns represent every simulated path.

In [73]:
def simulate_path(s0, mu, sigma, horizon, timesteps, n_sims):
    # Set the random seed for reproducibility
    # Same seed leads to the same set of random values
    random.seed(10000) 

    # Read parameters
    S0 = s0         # initial spot level
    r = mu          # mu = rf in risk neutral framework 
    T = horizon     # time horizion
    t = timesteps   # number of time steps
    n = n_sims      # number of simulation
    
    # Define dt
    dt = T/t        # length of time interval  
    
    # Simulating 'n' asset price paths with 't' timesteps
    S = zeros((t+1, n))
    S[0] = S0
    
    for i in range(1, t+1):
        z = random.standard_normal(n)     # psuedo random numbers
        S[i]=S[i-1]+r*S[i-1]*dt+sigma * sqrt(dt)*S[i-1]*z #  Euler-Maruyama scheme
    return S

The function caculate_exotics_price is used to caculate exotics prices. it has 6 aguments:

  • S_path: simulated price path data of which rows represent time, columns represent every simulated path [dataframe]
  • sampling_period: sampling_period×δt is time between two times sampling [int]
  • E: delivery price [float]
  • r: risk free interest/year [float]
  • horizon: time horizion/year [float]

The return is a list containing different extotic option prices.

In [74]:
def caculate_exotic_price(S_path,sampling_period,E,r,horizon):  
    
    S=S_path   #simulated price path data,expected as a dataframe,of which rows represent time,columns represent every simulated path
    sp=sampling_period  #sampling_period refers the days  sampling once
    #For example,sample_days=5,meaning that 5,10,15,...,250 are sampled to caculate Asian average and lookback max & min
    T=horizon
    final_price=S.iloc[-1] #final price at maturity
    path_mean=S.iloc[sp::sp].mean(axis=0)  # state variable MEAN related to sample period,a path has one
    path_max=S.iloc[sp::sp].max(axis=0)    # state variable MAX related to sample period,a path has one
    path_min=S.iloc[sp::sp].min(axis=0)   # state variable MIN related to sample period,a path has one

    # Calculate the discounted value of the expeced payoff
    #vanilla
    C0 = exp(-r*T) * mean(maximum(final_price - E, 0))
    P0 = exp(-r*T) * mean(maximum(E - final_price, 0))
    
    #fixed Asian
    fix_Asian_C = exp(-r*T) * mean(maximum(path_mean - E, 0))
    fix_Asian_P = exp(-r*T) * mean(maximum(E - path_mean, 0))

    float_Asian_C = exp(-r*T) * mean(maximum(path_mean - final_price, 0))
    float_Asian_P = exp(-r*T) * mean(maximum(final_price - path_mean, 0))

    fix_Lookback_C = exp(-r*T) * mean(maximum(path_max - E, 0))
    fix_Lookback_P = exp(-r*T) * mean(maximum(E - path_min, 0))

    float_Lookback_C = exp(-r*T) * mean(maximum(path_max - final_price, 0))
    float_Lookback_P = exp(-r*T) * mean(maximum(final_price - path_min, 0))
    
    # the caculated results are putted into 'reslut_list' as a list
    reslut_list=[C0,P0,fix_Asian_C,fix_Asian_P,float_Asian_C,float_Asian_P,\
    fix_Lookback_C,fix_Lookback_P,float_Lookback_C,float_Lookback_P]
    return reslut_list 

3. Initial Problem

Generate Simulated Path

We set inputs according to initial example above. Simulate underlying asset prices and visualize them.

In [75]:
# Assign simulated price path to dataframe for analysis and plotting
price_path = pd.DataFrame(simulate_path(100, 0.05, 0.20, 1, 252, 100000)) # timesteps=252 meaning simulating by days
# Verify the generated price paths
price_path.tail()
Out[75]:
0 1 2 3 4 5 6 7 8 9 ... 99990 99991 99992 99993 99994 99995 99996 99997 99998 99999
248 122.527621 73.744449 130.293612 85.286610 97.907263 144.821862 80.365324 115.746006 146.042448 92.667492 ... 115.599845 97.862926 78.233842 125.844117 66.377655 101.677147 98.078113 106.814941 116.481455 88.013134
249 123.271121 75.682955 129.660079 83.921614 98.727483 145.548026 79.898918 115.616426 143.093503 93.073108 ... 114.147618 98.887153 78.422099 123.627125 67.280394 103.011064 97.251055 107.642559 117.115391 88.060111
250 120.191906 74.536892 129.869937 83.268608 99.416004 145.089888 79.993577 115.108866 145.587400 94.805701 ... 113.254915 100.110953 79.943853 123.433024 67.710034 102.352844 97.816085 105.761352 119.361116 90.104125
251 120.814872 74.275841 130.515406 82.686641 97.362695 142.820721 80.835690 112.092138 147.169900 95.467139 ... 112.841938 99.666244 80.744836 122.955212 67.126030 102.426291 98.879244 107.860361 119.470899 86.796022
252 119.390993 76.142464 129.439476 81.154974 98.216171 143.485011 82.395154 112.095875 149.750083 95.320344 ... 113.809701 99.880452 81.904375 124.212596 66.906946 102.538933 98.768511 107.839947 122.292859 86.157439

5 rows × 100000 columns

In [76]:
# Plot the histogram of the simulated price path at maturity
price_path.iloc[-1].iplot(kind='histogram', title= 'Simulated Underlying Asset Price at Maturity', bins=100)
608010012014016018020022005001000150020002500300035004000Export to plot.ly »
Simulated Underlying Asset Price at Maturity
In [77]:
# Plot simulated price paths,1-100th
price_path.iloc[:,:100].iplot(title='Simulated Underlying Asset Price Paths', xTitle='Time Steps', yTitle='Price')
05010015020025080100120140160180Export to plot.ly »
0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899Simulated Underlying Asset Price PathsTime StepsPrice

Analyse: From the histogram above, it is clearly seen that price at maturity is subject to right-skewed log-normal distribution. Some extreme data bigger than mean about 100 is dangerous for call option short compared standard normal distribution.

Caculate Exotic Option based on Simulated Price Path

Caculate diffrent option prices by sampling by 1 Day, 1 Week, 1 Month, 1 quarter, semi-year,1 year based on the data simulated above.

In [78]:
Change_range=[1,5,21,63,126,252] #Sampling by 1 Day,1 Week,1 Month,1 quarter,semi-year,1 year

Change=[]# set a list to save data
for d in Change_range:
    reslut_list=caculate_exotic_price(price_path,d,100,0.05,1) # for different sampling periods caculate extotic price
    Change.append(reslut_list)# put caculate reslut into the list
    

df=pd.DataFrame(Change)# to dataframe
df.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df.index=Change_range
df.index.name="Sampling Period"
round(df,4)# keep 4 decimals
Out[78]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
Sampling Period
1 10.3968 5.5939 5.7586 3.3505 3.4241 5.8187 18.3100 11.7697 13.4828 16.5374
5 10.3968 5.5939 5.8040 3.3772 3.4154 5.7914 17.2590 11.0212 12.4587 15.7013
21 10.3968 5.5939 6.1321 3.5300 3.2435 5.4443 15.7177 9.8199 10.4130 13.8452
63 10.3968 5.5939 6.9111 3.9045 2.8556 4.6518 13.7253 8.2867 7.4580 10.6794
126 10.3968 5.5939 8.0738 4.4636 2.2346 3.4272 12.1393 7.0213 4.4691 6.8545
252 10.3968 5.5939 10.3968 5.5939 0.0000 0.0000 10.3968 5.5939 0.0000 0.0000

Analyse: From the table, it clearly seen that:

Firstly, European call and put option is not related to sampling period since their payoff functions are only about final price.

Then, Asian call and put with fixed delivery increase with the increase of sampling period,since the mean function is increasingly volatile when sampling period increases. If the sampling period is 252, the mean is reduced to final price ST, so the price of Asian call and put with fixed delivery is same as European call and put option respectively.

However, lookback call and put with fixed delivery has the opposite conclusion: the option prices decrease with the increase of sampling period as a result of stability of maximum and minimum function with sampling period increasing.

Last, All option with float delivery decrease with the increase of sampling period because the mean, maximum and minimum are all reduced to final price, which are equals float delivery ST if the sampling period is 252. Under this situation, their prices equal 0 though there hardly exists option of which sampling period equals time to expiry in practice. We assume this only for mathematic analysis.

4. Vary the Data

Change S0

Set sampling period to be 21. Caculate diffrent option prices with S0 varies from 60 to 150, step is 5.

In [79]:
Change_range=range(60,155,5)

Change=[]
for s0 in Change_range:
    price_path = pd.DataFrame(simulate_path(s0, 0.05, 0.20, 1, 252, 100000)) # timesteps=252 meaning simulating by days
    reslut_list=caculate_exotic_price(price_path,21,100,0.05,1)
    Change.append(reslut_list)
    
##################################### make table ####################################################

df=pd.DataFrame(Change)
df.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df.index=Change_range
df.index.name="S0"

##################################### visualize ####################################################
df.iplot(title='change S0', xTitle='S0', yTitle='Price')
round(df,4)
60708090100110120130140150010203040506070Export to plot.ly »
European CallEuropean PutFix Asian CallFix Asian putFloat Asian CallFloat Asian PutFix Lookback CallFix Lookback PutFloat Lookback CallFloat Lookback Putchange S0S0Price
Out[79]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
S0
60 0.0564 35.2239 0.0000 36.4880 1.9461 3.2666 0.0705 43.4746 6.2478 8.3071
65 0.1735 30.3447 0.0020 31.6037 2.1083 3.5388 0.2256 39.1705 6.7684 8.9994
70 0.4431 25.6179 0.0133 26.7288 2.2705 3.8110 0.5967 34.8665 7.2891 9.6916
75 0.9654 21.1440 0.0711 21.9003 2.4327 4.0832 1.3315 30.5625 7.8097 10.3839
80 1.8471 17.0294 0.2700 17.2129 2.5948 4.3555 2.6080 26.2585 8.3304 11.0761
85 3.1933 13.3793 0.7777 12.8344 2.7570 4.6277 4.6073 21.9552 8.8510 11.7684
90 5.0601 10.2498 1.8119 8.9824 2.9192 4.8999 7.4414 17.6714 9.3717 12.4607
95 7.4685 7.6620 3.5664 5.8506 3.0814 5.1721 11.1650 13.5267 9.8923 13.1529
100 10.3968 5.5939 6.1321 3.5300 3.2435 5.4443 15.7177 9.8199 10.4130 13.8452
105 13.7890 3.9899 9.4542 1.9659 3.4057 5.7165 20.8560 6.8454 10.9336 14.5374
110 17.5856 2.7902 13.3867 1.0121 3.5679 5.9888 26.2706 4.6555 11.4543 15.2297
115 21.7068 1.9151 17.7413 0.4804 3.7301 6.2610 31.7691 3.1109 11.9749 15.9220
120 26.0794 1.2913 22.3598 0.2127 3.8922 6.5332 37.2839 2.0473 12.4956 16.6142
125 30.6408 0.8565 27.1221 0.0888 4.0544 6.8054 42.8006 1.3261 13.0162 17.3065
130 35.3395 0.5589 31.9554 0.0359 4.2166 7.0776 48.3175 0.8465 13.5369 17.9987
135 40.1375 0.3606 36.8197 0.0138 4.3788 7.3498 53.8344 0.5341 14.0575 18.6910
140 45.0036 0.2304 41.6968 0.0048 4.5410 7.6221 59.3514 0.3330 14.5782 19.3833
145 49.9154 0.1459 46.5799 0.0016 4.7031 7.8943 64.8683 0.2059 15.0988 20.0755
150 54.8577 0.0919 51.4651 0.0005 4.8653 8.1665 70.3852 0.1275 15.6195 20.7678

Analyse: From the figure, it is clearly seen that all call option prices increase with the rise of S0 while all put option prices decrease. Moreover, the change magnitude of options with fixed delivery price is larger than options with floating delivery price.

Change E

For European call option, the price is a convex function of the delivery price. We can prove it easily.The payoff function max(STE,0) is a convex function of the delivery price. since expection integral has property of convexity preserving, so

C=erTmax(STE,0)p(ST,T,S0,0)dST

is also a convex function of the delivery price, where p(ST,T,S0,0) is transition density function of underlying price.

It is easy to prove that a line joining any two points on the graph of convex function lies on or above the graph. Let C(E) denote the call option price as a function of strike E. Then this is equivalent to saying, for E1<E2,

θC(E1)+(1θ)C(E2)C(θE1+(1θ)E2), for all 0θ1.()

The important thing to note here is that the final payoff is convex in strike for a fixed value in the underlying, that is the function max(STE,0) is convex in E. With this in mind, consider a portfolio long θ call options struck at E1, long (1θ) options struck at E2 and short one option struck at θE1+(1θ)E2 (all options with the same maturity). Since the final payoff is convex in strike, () holds at the expiry of the options and we therefore have that our portfolio has non-negative value at expiry. If C(E) violates convexity at some time before expiry, We can buy/short the portfolio above to make butterfly arbitrage.

The similary conclusion can also be drawed about put option. But what about extotic options? Are their convexities different? We change the E from 50 to 150 to see the affect on the option price with setting sampling period is 21.We eliminates options with floating delivery not related to E.

In [80]:
price_path = pd.DataFrame(simulate_path(100, 0.05, 0.20, 1, 252, 100000)) # reset
Change_range=range(50,155,5)

Change=[]
for E in Change_range:
    reslut_list=caculate_exotic_price(price_path,21,E,0.05,1)
    Change.append(reslut_list)
    
##################################### make table ####################################################

df=pd.DataFrame(Change)
df.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df.index=Change_range
df.index.name="E"

##################################### visualize ####################################################
names=["European Call","European Put","Fix Asian Call","Fix Asian put","Fix Lookback Call","Fix Lookback Put"]
df=df[names]
df.iplot(title='Change E', xTitle='E', yTitle='Price')
round(df,4)
60801001201400102030405060Export to plot.ly »
European CallEuropean PutFix Asian CallFix Asian putFix Lookback CallFix Lookback PutChange EEPrice
Out[80]:
European Call European Put Fix Asian Call Fix Asian put Fix Lookback Call Fix Lookback Put
E
50 52.3647 0.0003 50.1635 0.0000 62.7773 0.0004
55 47.6108 0.0026 45.4074 0.0000 58.0212 0.0032
60 42.8636 0.0116 40.6512 0.0000 53.2650 0.0155
65 38.1376 0.0417 35.8952 0.0001 48.5089 0.0573
70 33.4642 0.1244 31.1407 0.0018 43.7527 0.1772
75 28.8969 0.3133 26.3971 0.0143 38.9966 0.4676
80 24.5126 0.6852 21.6977 0.0710 34.2404 1.0609
85 20.3951 1.3238 17.1374 0.2669 29.4850 2.1228
90 16.6283 2.3131 12.8917 0.7773 24.7402 3.8359
95 13.2804 3.7214 9.1651 1.8069 20.0796 6.3758
100 10.3968 5.5939 6.1321 3.5300 15.7177 9.8199
105 7.9762 7.9295 3.8535 6.0076 11.9325 14.0041
110 6.0035 10.7130 2.2801 9.1903 8.8573 18.5910
115 4.4379 13.9035 1.2740 12.9404 6.4534 23.3148
120 3.2267 17.4484 0.6739 17.0964 4.6234 28.0671
125 2.3089 21.2868 0.3375 21.5162 3.2600 32.8231
130 1.6328 25.3668 0.1599 26.0947 2.2716 37.5792
135 1.1404 29.6306 0.0724 30.7634 1.5657 42.3354
140 0.7867 34.0330 0.0313 35.4785 1.0663 47.0915
145 0.5366 38.5390 0.0132 40.2165 0.7186 51.8477
150 0.3624 43.1210 0.0057 44.9651 0.4779 56.6038

Analyse: According the figure above, European options and extotic options are all convex functions of the delivery price from our intuition. Lookback call with fixed delivery price > European call option > Asian call option with fixed delivery price consitently regardless of what E equals. However, for put option, Asian put option with fixed delivery price and European put option violate this consistence.

This give a approxiamte convexity estimate formula:

convexity=C++C2CΔE2

where C+=C(E+ΔE),C=C(EΔE).

We set ΔE=5, which is not very tiny but still can measure convexity roughly.

In [81]:
convex=4*(df.shift(-1)+df.shift(1)-2*df).round(6)#percentage
convex.iplot(title='Convexity Related to E', xTitle='E', yTitle='Convexity')
convex
608010012014000.511.522.533.5Export to plot.ly »
European CallEuropean PutFix Asian CallFix Asian putFix Lookback CallFix Lookback PutConvexity Related to EEConvexity
Out[81]:
European Call European Put Fix Asian Call Fix Asian put Fix Lookback Call Fix Lookback Put
E
50 NaN NaN NaN NaN NaN NaN
55 0.026692 0.026692 0.000000 0.000000 -0.000000 0.037816
60 0.084648 0.084648 0.000456 0.000456 0.000000 0.118056
65 0.210548 0.210548 0.006240 0.006240 -0.000000 0.312712
70 0.424572 0.424572 0.043492 0.043492 0.000000 0.681884
75 0.731824 0.731824 0.176612 0.176612 0.000068 1.211344
80 1.066996 1.066996 0.556628 0.556628 0.002608 1.874620
85 1.402900 1.402900 1.258172 1.258172 0.042944 2.604756
90 1.675816 1.675816 2.076940 2.076940 0.336572 3.307004
95 1.856960 1.856960 2.773916 2.773916 1.194620 3.617056
100 1.852380 1.852380 3.017852 3.017852 2.307104 2.960280
105 1.791352 1.791352 2.820492 2.820492 2.839632 1.610860
110 1.628188 1.628188 2.269588 2.269588 2.685512 0.547304
115 1.417764 1.417764 1.623580 1.623580 2.295684 0.114228
120 1.173632 1.173632 1.055108 1.055108 1.866088 0.014748
125 0.966768 0.966768 0.635008 0.635008 1.500112 0.000660
130 0.734976 0.734976 0.360536 0.360536 1.130340 0.000000
135 0.554332 0.554332 0.185800 0.185800 0.825684 -0.000000
140 0.414704 0.414704 0.091556 0.091556 0.606672 0.000000
145 0.303652 0.303652 0.042432 0.042432 0.428060 0.000000
150 NaN NaN NaN NaN NaN NaN

Analyse: The results from table above are percentage. For European option and Asian option with fixed delivery price, the convexity of call and put are same. Analogy with the gamma of call and put are same, it can be understood easily. What figure above shows consistents with our experience is that the convexity of European option is greatest when it is at the money. And exotic options are no exceptiones. The data shows that the convexity of Asian option at the money is greater than any others, which implies there may be more butterfly arbitrage profits if opportunity appears.

Change σ, still Constant Volatility Asumption

Set sampling period to be 21. Caculate diffrent option prices with σ varies from 0.05 to 0.35, step is 0.01.

In [82]:
Change_range=arange(0.05,0.35,0.01)

Change=[]
for Sig in Change_range:
    price_path = pd.DataFrame(simulate_path(100, 0.05, Sig, 1, 252, 100000)) # timesteps=252 meaning simulating by days
    reslut_list=caculate_exotic_price(price_path,21,100,0.05,1)
    Change.append(reslut_list)
    
##################################### make table ####################################################
df=pd.DataFrame(Change)
df.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df.index=Change_range
df.index.name="sigma"

##################################### visualize ####################################################
df.iplot(title='Change Vol', xTitle='Vol', yTitle='Price')
0.050.10.150.20.250.30510152025Export to plot.ly »
European CallEuropean PutFix Asian CallFix Asian putFloat Asian CallFloat Asian PutFix Lookback CallFix Lookback PutFloat Lookback CallFloat Lookback PutChange VolVolPrice

Analyse: As we know, option prices rise as volatility rises. From the figure above, vega of lookback options is larger than Asian options because the trend of lookback options is more steep.

Change σ , under Stochastic Volatility Asumption

Stochastic volatility models take both the underlying price process and volatility process to be stochastic. There are many popular forms for the volatility process, the SABR model, for example, under the future measure, uses

dF=αFβdW1dα=vαdW2dW1dW2=ρdtF(0)=F0α(0)=α0

where F is future price er(Tt)S, β is elasticity of Variance, α is stochastic volatility rate, v is the volatility of volatility. W1 and W2 are Brownian motions with correlation ρ. F0 and α0 are initial future price and volatility respectively.

For

dF=αFβdW1

note

S=er(Tt)F

by Ito^ lemma,we can get

dS=der(Tt)F=er(Tt)dF+Fder(Tt)=αer(Tt)FβdW1+rFer(Tt)dt=αe(β1)r(Tt)SβdW1+rSdt=rSdt+αer(β1)(Tt)SβdW1

When interest rate is not random, T=Q. We can use the expected value of the discounted payoff under the future measure T(or say Q )

V(S,t)=er(Tt)ET[Payoff(FT)]=er(Tt)EQ[Payoff(ST)]

Redefine Function

The function SV_simulate_path is used to simulate the underlying asset price paths under stochastic volatility asumption. it has 8 aguments:

  • s0: initial spot level [float]
  • mu: mu = rf in risk neutral framework / year [float]
  • beta: elasticity of variance coefficient [float]
  • v: the volatility of volatility [float]
  • alpha: α0 are initial volatility [float]
  • horizon: time horizion / year [float]
  • timesteps: number of time steps [int]
  • n_sims: number of simulation [int]

The return is a array shape of which is (timesteps+1)×n_sims. Its rows represent time, columns represent every simulated path.

In [83]:
# redefine simulate_path
#to make sigma be a function of S,which is called stocastical volatility,a represent of which is SABR
def SV_simulate_path(s0, mu, beta, v, alpha, rho, horizon, timesteps, n_sims):
    
    # Set the random seed for reproducibility
    # Same seed leads to the same set of random values
    random.seed(10000) 

    # Read parameters
    S0 = s0         # initial spot level
    r = mu          # mu = rf in risk neutral framework 
    T = horizon     # time horizion
    t = timesteps   # number of time steps
    n = n_sims      # number of simulation
    
    # Define dt
    dt = T/t        # length of time interval  
    
    # Simulating 'n' asset price paths with 't' timesteps
    S = zeros((t+1, n))
    a= zeros((t+1, n))
    S[0] = S0
    a[0] = alpha
    for i in range(1, t+1):
        z=random.multivariate_normal([0,0],[[1,rho],[rho,1]],size=n)
        w1=z[:,0]
        w2=z[:,1]
        a[i]=a[i-1]+v*a[i-1]*sqrt(dt)*w2
        S[i]=S[i-1]+r*S[i-1]*dt+a[i]*exp((beta-1)*r*(T-i*dt))*pow(S[i-1],beta)* sqrt(dt)*w1 #  Euler-Maruyama scheme
    return S

Generate Simulated Path under Stochastic Volatility Asumption

Simulate underlying asset prices under stochastic volatility asumption and visualize them.

We set beta=1, v=0.4, alpha=0.2, rho=0.2. Other parameters are the same as default values above.

Next we only let one parameter varies, and others keep the above settings.

In [84]:
SV_price_path = pd.DataFrame(SV_simulate_path(s0=100, mu=0.05, beta=1, v=0.3, alpha=0.2, rho=0.2, horizon=1, timesteps=252, n_sims=100000))
# timesteps=252 meaning simulating by days

# Plot the histogram of the simulated price path at maturity
SV_price_path.iloc[-1].iplot(kind='histogram', title= 'Simulated Underlying Asset Price at Maturity under Stochastic Volatility Asumption', bins=100)

# Plot simulated price paths,1-100th
SV_price_path.iloc[:,:100].iplot(title='Simulated Underlying Asset Price Paths under Stochastic Volatility Asumption', xTitle='Time Steps', yTitle='Price')
5010015020025030035002k4k6k8k10kExport to plot.ly »
Simulated Underlying Asset Price at Maturity under Stochastic Volatility Asumption
0501001502002506080100120140160180Export to plot.ly »
0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899Simulated Underlying Asset Price Paths under Stochastic Volatility AsumptionTime StepsPrice

Analyse: Contrast constant volatility, simulated underlying asset prices at maturity under atochastic volatility asumption look higher peak and fat tail. Additionally, there are also more extreme data.

Change v, vol of vol

Caculate diffrent option prices with v varies from 0 to 1, step is 0.1.

In [85]:
Change_range=arange(0.00,1,0.1)

Change=[]
for v in Change_range:
    SV_price_path = pd.DataFrame(SV_simulate_path(s0=100, mu=0.05, beta=1, v=v, alpha=0.2, rho=0.2, horizon=1, timesteps=252, n_sims=100000))
    reslut_list=caculate_exotic_price(SV_price_path,21,100,0.05,1)
    Change.append(reslut_list)
    
##################################### make table ####################################################
df=pd.DataFrame(Change)
df.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df.index=Change_range
df.index.name="vol of vol"
##################################### visualize ####################################################
df.iplot(title='Change v', xTitle='v', yTitle='Price')
round(df,4)
00.10.20.30.40.50.60.70.80.92468101214161820Export to plot.ly »
European CallEuropean PutFix Asian CallFix Asian putFloat Asian CallFloat Asian PutFix Lookback CallFix Lookback PutFloat Lookback CallFloat Lookback PutChange vvPrice
Out[85]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
vol of vol
0.0 10.4458 5.5679 6.1590 3.5320 3.2120 5.4630 15.7528 9.8040 10.3671 13.8978
0.1 10.6970 5.4207 6.2883 3.4487 3.1484 5.5851 16.0772 9.6199 10.3024 14.0994
0.2 10.9666 5.2896 6.4250 3.3719 3.0911 5.7151 16.4219 9.4527 10.2540 14.3177
0.3 11.2554 5.1749 6.5692 3.3018 3.0405 5.8537 16.7896 9.3031 10.2242 14.5538
0.4 11.5639 5.0767 6.7213 3.2385 2.9976 6.0020 17.1819 9.1717 10.2145 14.8086
0.5 11.8921 4.9945 6.8811 3.1816 2.9627 6.1608 17.6017 9.0585 10.2272 15.0830
0.6 12.2418 4.9288 7.0491 3.1314 2.9369 6.3322 18.0525 8.9633 10.2650 15.3772
0.7 12.6132 4.8780 7.2256 3.0876 2.9204 6.5176 18.5413 8.8846 10.3328 15.6927
0.8 13.0083 4.8422 7.4111 3.0503 2.9136 6.7189 19.0753 8.8221 10.4367 16.0311
0.9 13.4279 4.8211 7.6061 3.0194 2.9166 6.9367 19.6695 8.7736 10.5905 16.3913

Analyse: Although the option prices rise as the volatility is rising, this conclusion is not necessarily established for the volatility of volatility. Option prices increase with v. if v=0, the situation is same as constant volatility model.

Change β

Caculate diffrent option prices with β varies from 0.5 to 1.1,step is 0.1.

In [86]:
Change_range=arange(0.5,1.1,0.1)

Change=[]
for b in Change_range:
    SV_price_path = pd.DataFrame(SV_simulate_path(s0=100, mu=0.05, beta=b, v=0.5, alpha=0.2, rho=0.2, horizon=1, timesteps=252, n_sims=100000))
    reslut_list=caculate_exotic_price(SV_price_path,21,100,0.05,1)
    Change.append(reslut_list)
    
##################################### make table ####################################################
df=pd.DataFrame(Change)
df.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df.index=Change_range
df.index.name="beta"
##################################### visualize ####################################################
df.iplot(title='Change Elasticity of Variance Coefficient', xTitle='Elasticity of Variance Coefficient', yTitle='Price')
round(df,4)
0.50.60.70.80.911.10510152025Export to plot.ly »
European CallEuropean PutFix Asian CallFix Asian putFloat Asian CallFloat Asian PutFix Lookback CallFix Lookback PutFloat Lookback CallFloat Lookback PutChange Elasticity of Variance CoefficientElasticity of Variance CoefficientPrice
Out[86]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
beta
0.5 5.0766 0.0066 2.7298 0.0048 0.0139 2.3588 5.2414 0.1339 0.1712 4.7960
0.6 5.2540 0.0691 2.8415 0.0548 0.0765 2.4747 5.7012 0.4638 0.5122 5.2279
0.7 5.7145 0.3461 3.1407 0.2557 0.2718 2.7552 6.6866 1.2207 1.2910 6.1316
0.8 6.7308 1.0690 3.7772 0.7350 0.7101 3.3298 8.5683 2.6583 2.8126 7.7864
0.9 8.6313 2.4980 4.9324 1.6385 1.5342 4.3737 11.8883 5.1111 5.5248 10.5782
1.0 11.8921 4.9945 6.8811 3.1816 2.9627 6.1608 17.6017 9.0585 10.2272 15.0830
1.1 17.3206 9.1511 10.0802 5.7185 5.3861 9.1939 27.6627 15.1751 18.5730 22.1817

Analyse: Option prices increase with elasticity of variance coefficient rises.

Change ρ

Caculate diffrent option prices with ρ varies from -1 to 1, step is 0.1.

In [87]:
Change_range=arange(-1,1.1,0.1)

Change=[]
for p in Change_range:
    SV_price_path = pd.DataFrame(SV_simulate_path(s0=100, mu=0.05, beta=1, v=0.5, alpha=0.2, rho=p, horizon=1, timesteps=252, n_sims=10000))
    reslut_list=caculate_exotic_price(SV_price_path,21,100,0.05,1)
    Change.append(reslut_list)
    
##################################### make table ####################################################
df=pd.DataFrame(Change)
df.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df.index=Change_range.round(1)
df.index.name="beta"

##################################### visualize ####################################################
df.iplot(title='Change Correlation Coefficient', xTitle='Correlation Coefficient', yTitle='Prices')
round(df,4)
−1−0.500.51510152025Export to plot.ly »
European CallEuropean PutFix Asian CallFix Asian putFloat Asian CallFloat Asian PutFix Lookback CallFix Lookback PutFloat Lookback CallFloat Lookback PutChange Correlation CoefficientCorrelation CoefficientPrices
Out[87]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
beta
-1.0 5.6954 9.9034 3.6660 5.9702 4.8953 2.9916 9.1795 14.6273 12.5766 9.8022
-0.9 6.0873 9.4825 3.8467 5.7051 4.7379 3.2010 9.7414 14.1849 12.3520 10.1614
-0.8 6.4885 9.0490 4.0576 5.4521 4.5798 3.4137 10.3260 13.7348 12.1382 10.5308
-0.7 6.9126 8.6209 4.2792 5.2016 4.4241 3.6381 10.9382 13.2826 11.9335 10.9132
-0.6 7.3579 8.1964 4.5120 4.9546 4.2662 3.8704 11.5773 12.8268 11.7363 11.3094
-0.5 7.8258 7.7767 4.7567 4.7124 4.1079 4.1126 12.2437 12.3659 11.5463 11.7176
-0.4 8.3158 7.3607 5.0124 4.4738 3.9500 4.3664 12.9345 11.9016 11.3608 12.1404
-0.3 8.8287 6.9488 5.2818 4.2414 3.7930 4.6326 13.6497 11.4351 11.1771 12.5784
-0.2 9.3718 6.5477 5.5639 4.0144 3.6351 4.9097 14.3903 10.9662 10.9955 13.0324
-0.1 9.9433 6.1550 5.8598 3.7935 3.4757 5.1977 15.1521 10.4954 10.8165 13.5041
-0.0 10.6087 5.7804 6.2143 3.5652 3.3047 5.4839 15.9311 9.9637 10.6085 13.9567
0.1 11.2892 5.3607 6.6406 3.3738 3.1136 5.7753 16.9023 9.4198 10.4839 14.4840
0.2 11.9372 4.9811 6.9733 3.1650 2.9514 6.0992 17.7415 8.9541 10.3193 15.0184
0.3 12.6166 4.6100 7.3198 2.9620 2.7910 6.4397 18.6067 8.4890 10.1572 15.5759
0.4 13.3263 4.2456 7.6815 2.7661 2.6318 6.7971 19.4981 8.0270 9.9965 16.1570
0.5 14.0690 3.8899 8.0585 2.5774 2.4715 7.1695 20.4177 7.5670 9.8391 16.7632
0.6 14.8494 3.5472 8.4505 2.3955 2.3121 7.5593 21.3668 7.1139 9.6864 17.3957
0.7 15.6651 3.2148 8.8589 2.2218 2.1542 7.9675 22.3480 6.6719 9.5411 18.0633
0.8 16.5211 2.8979 9.2805 2.0537 1.9952 8.3916 23.3602 6.2372 9.4019 18.7659
0.9 17.4109 2.5922 9.7127 1.8900 1.8380 8.8339 24.4045 5.8184 9.2703 19.5017
1.0 18.3056 2.2967 10.1412 1.7338 1.6913 9.2929 25.4645 5.4299 9.1610 20.2687

Analyse: Call options with fixed delivery price increase with the correlation coefficient rises while put options with fixed delivery price decrease with the correlation coefficient rises. Options with floating delivery price have contrary conclusion.

5. Conclusion

This is a mini project to price exotic options for the appropriate form of payoff, to consider Asian and lookback options using the Euler-Maruyama scheme. These option includes Asian call option with fixed delivery price, Asian put option with fixed delivery price, Asian call option with floating delivery price, Asian put option with floating delivery price, Lookback call option with fixed delivery price, Lookback put option with fixed delivery price, Lookback call option with floating delivery price, Lookback put option with floating delivery price.

We caculate diffrent option prices by sampling by 1 Day, 1 Week, 1 Month, 1 quarter, semi-year, 1 year. Asian call and put with fixed delivery increase with the increase of sampling period. But lookback call and put with fixed delivery has the opposite conclusion.

Then vary the data, we find

  • Change S0: all call option prices increase with the rise of S0 while all put option prices decrease. Moreover, the change magnitude of options with fixed delivery price is larger than options with floating delivery price.

  • Change E: extotic options are all convex functions of the delivery price. The data shows that the convexity in E of Asian option at the money is greater than any others.

  • Change σ: all option prices rise as volatility rises. Vega of lookback options is larger than Asian options.

We also simulate underlying asset prices under stochastic volatility asumption, find that:

Contrast constant volatility, simulated underlying asset prices at maturity under atochastic volatility asumption look higher peak and fat tail. Moreover, there are also more extreme data.

We make some detailed exploration for exotic option pricing under stochastic volatility asumption by varing the parameters of stochastic volatility model.

6. Reference

  • Riaz Ahmad, CQF_June_2021_M3L4_Blank
  • Kannan.Singaravelu, Python Labs Monte Carlo
  • Paul Wilmott, Paul Wilmott on Quantitative Finance Vol 3
  • Mark Joshi, Quant Job Interview Questions and Answers

Appendix

Discrete Approximation Numerical Error

Let dt=1/100, 1/200, 1/300,...1/30000, for fixed dt, we can caculate the mean absolute error of closed-form solutions and numerical solutions. Then we simulate different 100 price paths to caculate mean absolute error, and average them. For every dt,we get a averaged mean absolute error, and plot it.

In [41]:
def analysis_dt(t):
#random.seed(10000)
    S0=100
    #t=100
    sigma=0.2
    dt=1/t
    r=0.05

    W=cumsum([0]+list(random.standard_normal(t)))
    S = zeros(t+1)
    Sd = zeros(t+1)
    S[0] = S0
    Sd[0] = S0
    for i in range(1,t+1):
        z=W[i]-W[i-1]
        S[i] = S[i-1] * exp((r - 0.5 * sigma ** 2) * dt + sigma * sqrt(dt) * z)# close-form
        Sd[i]=Sd[i-1]+r*Sd[i-1]*dt+sigma * sqrt(dt)*Sd[i-1]*z
    return S,Sd
In [64]:
error=[]
sample_num=100
for i in range(1,30):
    s=0
    for j in range(sample_num):
        S,Sd=analysis_dt(100*i)
        s+=mean(abs(S-Sd))
    error.append(s/sample_num)

plt.plot(1/(100*array(range(1,30))),error)
plt.xlabel('d t')
plt.ylabel('path error')
plt.grid()

If dt=1/252=0.004, path error is 0.1. for S=100, it is very small.

For dt=1/25, we plot closed-form solutions and numerical solutions and compare them.

In [63]:
S,Sd=analysis_dt(25)
df=pd.DataFrame([S,Sd]).T
df.columns=['S closed-form solution','S numerical solution']
df.iplot(title = 'Compare Closed-form Solution and Numerical Solution',color =['cornflowerblue','red'],xTitle='Time Steps', yTitle='Price') 
0510152025100110120130140150160170Export to plot.ly »
S closed-form solutionS numerical solutionCompare Closed-form Solution and Numerical SolutionTime StepsPrice

Random Error

In [33]:
def caculate_exotic_error(S_path,sampling_period,K,r=0.05,T=1):  
    #sampling_period refers Sampling once every sample_days days
    #For example,sample_days=5,meaning that 5,10,15,...,250 are sampled to caculate Asian average and lookback max & min
    S=S_path   #simulated price path data,expected as a dataframe,of which rows represent time,columns represent every simulated path
    sp=sampling_period  #
    final_price=S.iloc[-1] #final price at maturity
    path_mean=S.iloc[sp::sp].mean(axis=0)  # state variable MEAN related to sample period,a path has one
    path_max=S.iloc[sp::sp].max(axis=0)    # state variable MAX related to sample period,a path has one
    path_min=S.iloc[sp::sp].min(axis=0)   # state variable MIN related to sample period,a path has one

    # Calculate the discounted value of the expeced payoff
    #vanilla
    C0 = exp(-r*T) * std(maximum(final_price - K, 0))
    P0 = exp(-r*T) * std(maximum(K - final_price, 0))
    
    #fixed Asian
    fix_Asian_C = exp(-r*T) * std(maximum(path_mean - K, 0))
    fix_Asian_P = exp(-r*T) * std(maximum(K - path_mean, 0))

    float_Asian_C = exp(-r*T) * std(maximum(path_mean - final_price, 0))
    float_Asian_P = exp(-r*T) * std(maximum(final_price - path_mean, 0))

    fix_Lookback_C = exp(-r*T) * std(maximum(path_max - K, 0))
    fix_Lookback_P = exp(-r*T) * std(maximum(K - path_min, 0))

    float_Lookback_C = exp(-r*T) * std(maximum(path_max - final_price, 0))
    float_Lookback_P = exp(-r*T) * std(maximum(final_price - path_min, 0))
    
    # the caculated results are putted into 'reslut_list' as a list
    reslut_list=[C0,P0,fix_Asian_C,fix_Asian_P,float_Asian_C,float_Asian_P,\
    fix_Lookback_C,fix_Lookback_P,float_Lookback_C,float_Lookback_P]
    return reslut_list 
In [35]:
Change_range=[1,5,21,63,126,252] #Sampling by 1 Day,1 Week,1 Month,1 quarter,semi-year,1 year

Change=[]
for d in Change_range:
    reslut_list=caculate_exotic_error(price_path,d,K=100,r=0.05,T=1)
    Change.append(reslut_list)


df1=pd.DataFrame(Change)*1.96/sqrt(100000)
df1.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df1.index=Change_range
df1.index.name="Sampling Period"
round(df1,4)

#df1 shows random error,95% credit level
Out[35]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
Sampling Period
1 0.1604 0.0903 0.0853 0.0555 0.0541 0.0943 0.1770 0.0871 0.1039 0.1611
5 0.1604 0.0903 0.0859 0.0560 0.0540 0.0939 0.1735 0.0879 0.1029 0.1591
21 0.1604 0.0903 0.0908 0.0586 0.0513 0.0883 0.1704 0.0895 0.1002 0.1530
63 0.1604 0.0903 0.1027 0.0648 0.0457 0.0754 0.1657 0.0905 0.0906 0.1369
126 0.1604 0.0903 0.1212 0.0738 0.0369 0.0548 0.1625 0.0908 0.0738 0.1096
252 0.1604 0.0903 0.1604 0.0903 0.0000 0.0000 0.1604 0.0903 0.0000 0.0000
In [38]:
Change_range=[1,5,21,63,126,252] #Sampling by 1 Day,1 Week,1 Month,1 quarter,semi-year,1 year

Change=[]
for d in Change_range:
    reslut_list=caculate_exotic_price(price_path,d,100,0.05,1)
    Change.append(reslut_list)
    

df2=pd.DataFrame(Change)
df2.columns=["European Call", "European Put", "Fix Asian Call", "Fix Asian put",\
                  "Float Asian Call","Float Asian Put","Fix Lookback Call","Fix Lookback Put",\
                  "Float Lookback Call","Float Lookback Put"]
df2.index=Change_range
df2.index.name="Sampling Period"
round(df2,4)
# repeat initial problem to caculate prices,and save to df2
Out[38]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
Sampling Period
1 15.6688 10.9174 8.8126 6.4216 6.5491 8.9095 30.3340 20.5748 25.5311 25.2773
5 15.6688 10.9174 8.8820 6.4728 6.5290 8.8712 28.3846 19.4229 23.5796 24.0242
21 15.6688 10.9174 9.3665 6.7814 6.1878 8.3541 25.4771 17.5885 19.6852 21.2408
63 15.6688 10.9174 10.5239 7.5358 5.4137 7.1771 21.7752 15.2022 14.0324 16.4897
126 15.6688 10.9174 12.2462 8.6604 4.1760 5.3416 18.8570 13.2042 8.3520 10.6832
252 15.6688 10.9174 15.6688 10.9174 0.0000 0.0000 15.6688 10.9174 0.0000 0.0000
In [40]:
#error percentage
df1/df2
Out[40]:
European Call European Put Fix Asian Call Fix Asian put Float Asian Call Float Asian Put Fix Lookback Call Fix Lookback Put Float Lookback Call Float Lookback Put
Sampling Period
1 0.010238 0.008269 0.009675 0.008650 0.008256 0.010581 0.005836 0.004232 0.004070 0.006372
5 0.010238 0.008269 0.009676 0.008650 0.008264 0.010580 0.006112 0.004524 0.004363 0.006623
21 0.010238 0.008269 0.009697 0.008642 0.008298 0.010573 0.006689 0.005088 0.005090 0.007202
63 0.010238 0.008269 0.009757 0.008602 0.008436 0.010508 0.007609 0.005955 0.006458 0.008302
126 0.010238 0.008269 0.009896 0.008516 0.008841 0.010262 0.008619 0.006875 0.008841 0.010262
252 0.010238 0.008269 0.010238 0.008269 NaN NaN 0.010238 0.008269 NaN NaN

We can see that random error is negligible, about ±1%, under 95% credit level, N=100000. It is necessary to use variance reduction technology if you request a higher digit.